using System;
using System.Collections.Generic;
using System.IO;
using System.Media;
using GTA;
using GTA.Native;

namespace CustomPeds;

public static class SoundHelper
{
    public enum PedSoundType
    {
        IsMaleAndNotHero,
        IsHero,
        NotHooker,
        IsHooker
    }

    private static SoundPlayer sp = new SoundPlayer();
    private static DateTime delay = default(DateTime);
    private static PedSoundType soundReplace;
    public static string TempVoiceName = string.Empty;
    private static List<string> hookers = new List<string> { "s_f_y_hooker_01_white_full_01", "s_f_y_hooker_01_white_full_02", "s_f_y_hooker_01_white_full_03", "s_f_y_hooker_02_white_full_01", "s_f_y_hooker_02_white_full_02", "s_f_y_hooker_02_white_full_03", "s_f_y_hooker_03_black_full_01", "s_f_y_hooker_03_black_full_03" };

    public static void PlayExternalSound(string sound, int toTimeMs = 0)
    {
        if (!(DateTime.Now > delay))
        {
            return;
        }
        using MemoryStream stream = new MemoryStream(Convert.FromBase64String(sound));
        sp.Dispose();
        sp.Stream = stream;
        sp.Play();
        if (toTimeMs > 0)
        {
            delay = DateTime.Now.AddMilliseconds(toTimeMs);
        }
    }

    public static void SetVoice(this Ped ped, string voice)
    {
        Function.Call((Hash)0x6C8065A3B780185Bul, ped, voice);
    }

    public static void PlayAmbientSpeech1(this Ped ped, string speechFile, bool immediately)
    {
        if (immediately)
        {
            Function.Call((Hash)0xB8BEC0CA6F0EDB0Ful, ped);
        }
        Function.Call((Hash)0xB9EFD5C25018725Aul, "IsDirectorModeActive", 1);
        Function.Call((Hash)0x8E04FEDD28D42462ul, ped, speechFile, "SPEECH_PARAMS_FORCE");
        Function.Call((Hash)0xB9EFD5C25018725Aul, "IsDirectorModeActive", 0);
    }

    public static void PlayAmbientSpeech2(this Ped ped, string speechFile, bool immediately, bool OnReplace = true)
    {
        if (immediately)
        {
            Function.Call((Hash)0xB8BEC0CA6F0EDB0Ful, ped);
        }
        Function.Call((Hash)0xB9EFD5C25018725Aul, "IsDirectorModeActive", 1);
        if (OnReplace)
        {
            if (Game.Player.Handle == ped.Handle)
            {
                PlaySoundReplace(speechFile, Main.P1, immediately);
            }
            else
            {
                PlaySoundReplace(speechFile, Main.P2, immediately);
            }
        }
        else
        {
            Function.Call((Hash)0xC6941B4A3A8FBBB9ul, ped, speechFile, "SPEECH_PARAMS_FORCE");
        }
        Function.Call((Hash)0xB9EFD5C25018725Aul, "IsDirectorModeActive", 0);
    }

    private static void GetPedSoundType(Origin origin)
    {
        if (origin.Character.Gender == Gender.Male && origin.skin.ModelName != "Franklin" && origin.skin.ModelName != "Michael" && origin.skin.ModelName != "Trevor")
        {
            soundReplace = PedSoundType.IsMaleAndNotHero;
        }
        if ((origin.Character.Gender == Gender.Male && origin.skin.ModelName == "Franklin") || Main.P1.skin.ModelName == "Michael" || origin.skin.ModelName == "Trevor")
        {
            soundReplace = PedSoundType.IsHero;
        }
        if (origin.Character.Gender == Gender.Female && origin.skin.ModelName.ToLower().IndexOf("hooker") == -1)
        {
            soundReplace = PedSoundType.NotHooker;
        }
        if (origin.Character.Gender == Gender.Female && origin.skin.ModelName.ToLower().IndexOf("hooker") >= 0)
        {
            soundReplace = PedSoundType.IsHooker;
        }
    }

    public static void PlaySoundReplace(string sound, Origin origin, bool immediately = false)
    {
        GetPedSoundType(origin);
        _ = soundReplace;
        if (soundReplace == PedSoundType.NotHooker)
        {
            TempVoiceName = hookers[new Random(Guid.NewGuid().GetHashCode()).Next(0, 7)];
            origin.Character.PlayAmbientSpeechWithVoice(sound, TempVoiceName, immediately);
        }
    }

    public static void PlayAmbientSpeechWithVoice(this Ped ped, string speechName, string voiceName, bool immediately)
    {
        if (immediately)
        {
            Function.Call((Hash)0xB8BEC0CA6F0EDB0Ful, ped);
        }
        Function.Call((Hash)0xB9EFD5C25018725Aul, "IsDirectorModeActive", 1);
        Function.Call((Hash)0x3523634255FC3318ul, ped, speechName, voiceName, "SPEECH_PARAMS_FORCE", 0);
        Function.Call((Hash)0xB9EFD5C25018725Aul, "IsDirectorModeActive", 0);
    }

    public static void IsSpeechPlayingToEnd(this Ped ped)
    {
        DateTime now = DateTime.Now;
        while (Function.Call<bool>((Hash)0x9072C8B49907BFADul, ped))
        {
            Script.Wait(300);
            if (DateTime.Now.Subtract(now).TotalMilliseconds >= 5000.0)
            {
                break;
            }
        }
    }
}


